package mn.idax.exchange.otc.aspect;

import com.alibaba.fastjson.JSON;
import mn.idax.exchange.auth.constant.LogCategoryEnum;
import mn.idax.exchange.auth.util.UUidUtils;
import mn.idax.exchange.common.UTCTimeUtil;
import mn.idax.exchange.otc.annotation.SysLog;
import mn.idax.exchange.otc.util.LogUtils;
import mn.idax.exchange.otc.util.ParamUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @Auther: dison
 * @Date: 2018/7/27 13:11
 * @Description:
 */
@Aspect
@Configuration
public class LogMethodAspect {

    /**
     *
     * 功能描述:
     *      定义注解切点
     * @auther: dison
     * @date: 2018/7/27 13:21
     */
    @Pointcut("@annotation(sysLog)")
    public void sysLogPoint(SysLog sysLog) {
    }

    /**
     *
     * 功能描述:
     *      定义web包目录切点
     * @auther: dison
     * @date: 2018/7/27 13:21
     */
    @Pointcut("execution(public * mn.idax.exchange.otc.web..*.*(..))")
    public void webPoint() {
    }

    /**
     *
     * 功能描述:
     *      定义service包目录切点
     * @auther: dison
     * @date: 2018/7/27 13:21
     */
    @Pointcut("execution(public * mn.idax.exchange.otc.service..*.*(..))")
    public void servicePoint() {
    }

    /**
     *
     * 功能描述:
     *      环绕通知：
     *          1.拦截切点web包或service包
     *          2.拦截的方法必须含有日志输出注解
     * @param:
     * @return:
     * @auther: dison
     * @date: 2018/7/27 14:06
     */
    @Around("(webPoint()|| servicePoint()) && sysLogPoint(sysLog)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint,SysLog sysLog) throws Throwable {
        // 返回参数
        Object returnVal = proceedingJoinPoint.proceed();
        // 1.判断注解是否禁用日志打印
        if (sysLog.ignore()){
            return returnVal;
        }
        String returnJson = JSON.toJSONString(returnVal);
        // 2.流水号
        String serilNo = UTCTimeUtil.getUTCTimeStringOne() + UUidUtils.getUUID();
        try {
            String methodName = proceedingJoinPoint.getSignature().getDeclaringTypeName()+" method:"+proceedingJoinPoint.getSignature().getName();

            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest();
            // 3.打印请求日志
            LogUtils.unifLog(this.getClass(), sysLog.level().getValue(),methodName,serilNo, LogCategoryEnum.REQUEST.getValue(), JSON.toJSONString(ParamUtils.treeMapToServletRequest(request)));
            // 4.打印返回日志
            LogUtils.unifLog(this.getClass(), sysLog.level().getValue(),methodName,serilNo,LogCategoryEnum.RESPONSE.getValue(), returnJson);
        } catch (Exception e) {
            LogUtils.error(LogMethodAspect.class,"doAround", e);
        }

        return returnVal;
    }
}
